package org.monkeyk.swing;

import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import java.util.Arrays;

/**
 * 2010-8-20
 * <p/>
 * 可排序的TableModel<br>
 * 在使用是需要调用sort方法并传递相应的列<br>
 * 如何使用?<br>
 * 对表的列头添加点击事件,并获取点击的列号调用sort方法,部分代码如:<br>
 * <code>
 * head.addMouseListener(new MouseAdapter() {
 * public void mouseClicked(MouseEvent e) {
 * if (e.getClickCount() != 1) { return; } //获取点击的列
 * int col = jTable1.columnAtPoint(e.getPoint()); //将列转化为model的列
 * int modCol =jTable1.convertColumnIndexToModel(col); //sort
 * sortModel.sort(modCol);
 * }
 * }); </code> 注意: 对应的表必须使用创建的SortTableModel实例<br>
 * <i>点击次数根据单双对应正序排列与倒序排序</i>
 *
 * @author mkk(monkeyking1987@126.com)
 *         参见 JAVA核心卷2 中对JTable的讲解
 */
public class SortTableModel extends AbstractTableModel {

    private static final long serialVersionUID = -3648878960007927383L;
    // 要排序的列
    private int sortCol;
    // 表模型
    private TableModel model;
    // 比较器集合
    private RowComparable rcs[];
    // 计数器,用于处理正序还是倒序排列
    private int count;

    /**
     * contrsctuor
     *
     * @param model 表格模型
     */
    public SortTableModel(TableModel model) {
        this.model = model;
        // 比较器初始化
        this.initComparable();
    }

    /**
     * contrscutor
     *
     * @param data        表格数据
     * @param columnNames 列名数据
     */
    public SortTableModel(Object[][] data, Object[] columnNames) {
        this.model = new DefaultTableModel(data, columnNames);
        this.initComparable();
    }

    /**
     * 比较器初始化
     */
    private void initComparable() {
        rcs = new RowComparable[model.getRowCount()];
        for (int i = 0; i < rcs.length; i++) {
            rcs[i] = new RowComparable();
            rcs[i].index = i;
        }
    }

    /**
     * 排序的方法
     *
     * @param sortCol 排序的列号,注意:必须是表格模型的列号
     */
    public void sort(int sortCol) {
        this.sortCol = sortCol;
        // sort
        Arrays.sort(rcs);
        // 通知表格模型改变
        this.fireTableDataChanged();
        count++;
        if (count == Integer.MAX_VALUE) {
            count = 0;
        }
    }

    public int getRowCount() {
        return model.getRowCount();
    }

    public int getColumnCount() {
        return model.getColumnCount();
    }

    public Object getValueAt(int r, int c) {
        return model.getValueAt(rcs[r].index, c);
    }

    @Override
    public void setValueAt(Object aValue, int r, int c) {
        this.model.setValueAt(aValue, rcs[r].index, c);
    }

    @Override
    public String getColumnName(int c) {
        return this.model.getColumnName(c);
    }

    @Override
    public Class<?> getColumnClass(int c) {
        return this.model.getColumnClass(c);
    }

    /**
     * 列对应的数据比较器<br>
     * 根据单元格数据类型来比较
     */
    private class RowComparable implements Comparable<RowComparable> {

        // 行索引号
        private int index;

        @SuppressWarnings({"unchecked", "rawtypes"})
        public int compareTo(RowComparable o) {
            Object a = model.getValueAt(index, sortCol);
            Object b = model.getValueAt(o.index, sortCol);
            // 处理有列数据为空的情况
            if (a == null || b == null) {
                return 0;
            }
            if (count % 2 == 0) {
                if (a instanceof Comparable) {
                    return ((Comparable) a).compareTo(b);
                } else {
                    return a.toString().compareTo(b.toString());
                }
            } else {
                if (b instanceof Comparable) {
                    return ((Comparable) b).compareTo(a);
                } else {
                    return b.toString().compareTo(a.toString());
                }
            }

        }
    }
}
